import 'dart:async';
import 'dart:convert';
import 'dart:developer' as developer;
import 'dart:io';
import 'dart:math';
// 导入生成的 Rust 绑定代码
// 注意：如果生成的代码中还没有 WebSocket 类型，将使用下面的占位符类型
// TODO: 当 Rust 绑定代码生成后，取消注释下面的导入并移除占位符类型
// import '../../generated/frb_generated.dart/frb_generated.dart';
// import 'package:flutter_rust_bridge/flutter_rust_bridge_for_generated.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:web_socket_channel/io.dart';
import '../config/app_config.dart';
import '../../shared/storage/storage_service.dart';

// 尝试从生成的代码中导入 Rust 类型
// 如果生成的代码中还没有这些类型，需要先运行代码生成：
// cd rust && flutter_rust_bridge_codegen generate

// 本地状态枚举（用于兼容性）
enum LocalWebSocketStatus {
  disconnected,
  connecting,
  connected,
  error,
}

// 临时占位符类型（如果生成的代码中还没有这些类型）
// TODO: 重新生成 Rust 绑定代码后，这些类型应该从 frb_generated.dart 导入
// 运行命令：cd rust && flutter_rust_bridge_codegen generate

// 临时占位符类型定义（用于编译，直到重新生成代码）
// 注意：这些是临时类型，实际应该从 frb_generated.dart 导入

/// 临时占位符：WebSocketStatus 枚举
/// 实际应该从 frb_generated.dart 导入
class WebSocketStatus {
  final String _value;
  const WebSocketStatus._(this._value);
  
  static const WebSocketStatus Disconnected = WebSocketStatus._('Disconnected');
  static const WebSocketStatus Connecting = WebSocketStatus._('Connecting');
  static const WebSocketStatus Connected = WebSocketStatus._('Connected');
  static WebSocketStatus Error(String message) => WebSocketStatus._('Error($message)');
  
  @override
  String toString() => _value;
  
  bool get isDisconnected => _value == 'Disconnected';
  bool get isConnecting => _value == 'Connecting';
  bool get isConnected => _value == 'Connected';
  bool get isError => _value.startsWith('Error');
}

/// 临时占位符：WebSocketMessage 结构
/// 实际应该从 frb_generated.dart 导入
class WebSocketMessage {
  final String data;
  final String messageType;
  
  WebSocketMessage({required this.data, required this.messageType});
}

/// 临时占位符：WebSocketManager 类
/// 实际应该从 frb_generated.dart 导入
/// 
/// 注意：由于代码生成工具配置问题，当前使用 Dart 实现作为临时方案
/// 真正的 Rust 实现需要重新生成绑定代码
class WebSocketManager {
  WebSocketChannel? _channel;
  WebSocket? _webSocket;
  StreamSubscription? _subscription;
  StreamSink<WebSocketStatus>? _statusSink;
  StreamSink<WebSocketMessage>? _messageSink;
  Timer? _pingTimer;
  
  WebSocketManager();
  
  void connect({
    required String subscriptionId,
    String? wsUrl,
    String? token,
    required StreamSink<WebSocketStatus> statusSink,
    required StreamSink<WebSocketMessage> messageSink,
  }) {
    _statusSink = statusSink;
    _messageSink = messageSink;
    
    // 使用 Dart WebSocket 实现作为临时方案
    // 注意：这是异步操作，但不等待完成（符合 Rust API 的设计）
    _connectDart(wsUrl ?? '', token ?? '', statusSink, messageSink).catchError((error) {
      developer.log('WebSocket connection error: $error');
      statusSink.add(WebSocketStatus.Error(error.toString()));
    });
  }
  
  Future<void> _connectDart(
    String wsUrl,
    String token,
    StreamSink<WebSocketStatus> statusSink,
    StreamSink<WebSocketMessage> messageSink,
  ) async {
    try {
      statusSink.add(WebSocketStatus.Connecting);
      
      final uri = Uri.parse(wsUrl);
      
      // 使用 IOWebSocketChannel.connect 会自动处理 WebSocket 握手
      // 但我们需要自定义 headers，所以使用手动升级方式
      final httpClient = HttpClient();
      final request = await httpClient.getUrl(uri);
      
      // 设置必要的 WebSocket 升级头
      request.headers.set('Upgrade', 'websocket');
      request.headers.set('Connection', 'Upgrade');
      
      // 生成 Sec-WebSocket-Key（WebSocket 握手必需）
      // 需要 16 字节的随机数据，然后进行 base64 编码
      final random = Random();
      final keyBytes = List<int>.generate(16, (_) => random.nextInt(256));
      final key = base64Encode(keyBytes);
      request.headers.set('Sec-WebSocket-Key', key);
      request.headers.set('Sec-WebSocket-Version', '13');
      
      // 设置自定义 headers
      request.headers.set('Authorization', 'Bearer $token');
      request.headers.set('User-Agent', 'VioletIM-Flutter');
      
      developer.log('Attempting WebSocket connection to: $uri', name: 'WebSocketManager');
      developer.log('Using token: ${token.substring(0, token.length > 20 ? 20 : token.length)}...', name: 'WebSocketManager');
      
      final response = await request.close();
      
      if (response.statusCode != 101) {
        String errorBody = '';
        try {
          errorBody = await response.transform(utf8.decoder).join();
        } catch (e) {
          errorBody = 'Could not read error body: $e';
        }
        developer.log('WebSocket upgrade failed: ${response.statusCode}', name: 'WebSocketManager');
        developer.log('Response headers: ${response.headers}', name: 'WebSocketManager');
        if (errorBody.isNotEmpty) {
          developer.log('Error body: $errorBody', name: 'WebSocketManager');
        }
        statusSink.add(WebSocketStatus.Error('WebSocket upgrade failed: ${response.statusCode}'));
        await response.drain();
        httpClient.close();
        return;
      }
      
      developer.log('WebSocket handshake successful', name: 'WebSocketManager');
      
      final socket = await response.detachSocket();
      _webSocket = WebSocket.fromUpgradedSocket(socket, serverSide: false);
      _channel = IOWebSocketChannel(_webSocket!);
      
      statusSink.add(WebSocketStatus.Connected);
      
      // 启动 ping 定时器
      _pingTimer = Timer.periodic(const Duration(seconds: 30), (timer) {
        if (_channel != null) {
          try {
            _channel!.sink.add(jsonEncode({
              'type': 'ping',
              'timestamp': DateTime.now().millisecondsSinceEpoch,
            }));
          } catch (e) {
            developer.log('Error sending ping: $e');
          }
        }
      });
      
      // 监听消息
      _subscription = _channel!.stream.listen(
        (message) {
          try {
            if (message is String) {
              // 检查是否是 pong 响应
              if (message == 'pong' || message.toLowerCase() == 'pong') {
                return;
              }
              
              try {
                final json = jsonDecode(message) as Map<String, dynamic>;
                if (json['type'] == 'pong' || json['type'] == 'ping') {
                  return;
                }
              } catch (_) {
                // 不是 JSON，继续处理
              }
              
              messageSink.add(WebSocketMessage(
                data: message,
                messageType: 'text',
              ));
            } else {
              messageSink.add(WebSocketMessage(
                data: message.toString(),
                messageType: 'binary',
              ));
            }
          } catch (e) {
            developer.log('Error handling message: $e');
          }
        },
        onError: (error) {
          developer.log('WebSocket error: $error');
          statusSink.add(WebSocketStatus.Error(error.toString()));
        },
        onDone: () {
          developer.log('WebSocket connection closed');
          statusSink.add(WebSocketStatus.Disconnected);
        },
        cancelOnError: false,
      );
    } catch (e) {
      developer.log('WebSocket connection failed: $e');
      statusSink.add(WebSocketStatus.Error(e.toString()));
    }
  }
  
  void disconnect() {
    _pingTimer?.cancel();
    _pingTimer = null;
    _subscription?.cancel();
    _subscription = null;
    _channel?.sink.close();
    _channel = null;
    _webSocket = null;
    _statusSink?.add(WebSocketStatus.Disconnected);
  }
  
  void send(String message) {
    if (_channel != null) {
      try {
        _channel!.sink.add(message);
      } catch (e) {
        developer.log('Error sending message: $e');
        throw Exception('Failed to send message: $e');
      }
    } else {
      throw Exception('WebSocket not connected');
    }
  }
}

/// 临时占位符：StreamSink 类
/// 实际应该从 flutter_rust_bridge_for_generated.dart 导入
class StreamSink<T> {
  final StreamController<T> _controller = StreamController<T>.broadcast();
  
  Stream<T> get stream => _controller.stream;
  
  void add(T value) {
    _controller.add(value);
  }
  
  void close() {
    _controller.close();
  }
}

/// 使用 Rust 实现的 WebSocket 服务
/// 这是完全基于 Rust 的 WebSocket 实现，替代了原来的 Dart WebSocket 实现
class WebSocketServiceRust {
  final StorageService _storageService;
  WebSocketManager? _manager;
  LocalWebSocketStatus _status = LocalWebSocketStatus.disconnected;
  StreamController<dynamic>? _messageController;
  StreamController<LocalWebSocketStatus>? _statusController;
  StreamSubscription<WebSocketMessage>? _messageSubscription;
  StreamSubscription<WebSocketStatus>? _statusSubscription;
  Timer? _reconnectTimer;
  int _reconnectAttempts = 0;
  static const int maxReconnectAttempts = 5;

  WebSocketServiceRust(this._storageService) {
    _messageController = StreamController<dynamic>.broadcast();
    _statusController = StreamController<LocalWebSocketStatus>.broadcast();
  }

  // 为了兼容性，提供与WebSocketService相同的接口
  LocalWebSocketStatus get status => _status;
  Stream<dynamic> get messageStream => _messageController!.stream;
  Stream<LocalWebSocketStatus> get statusStream => _statusController!.stream;
  
  // 兼容WebSocketStatus枚举（用于类型检查）
  bool get isConnected => _status == LocalWebSocketStatus.connected;

  Future<void> connect() async {
    if (_status == LocalWebSocketStatus.connected ||
        _status == LocalWebSocketStatus.connecting) {
      developer.log('WebSocket already connected or connecting, skipping', name: 'WebSocketServiceRust');
      return;
    }

    _status = LocalWebSocketStatus.connecting;
    _notifyStatusChange();
    developer.log('Connecting to WebSocket (Rust)...', name: 'WebSocketServiceRust');

    try {
      final token = await _storageService.getToken();
      if (token == null) {
        developer.log('No token found, cannot connect WebSocket', name: 'WebSocketServiceRust');
        _status = LocalWebSocketStatus.error;
        _notifyStatusChange();
        return;
      }

      // 获取subscription_id
      String? subscriptionId = await _storageService.getSubscriptionId();
      if (subscriptionId == null || subscriptionId.isEmpty) {
        final userInfoJson = await _storageService.getUserInfo();
        if (userInfoJson != null) {
          try {
            final userInfo = jsonDecode(userInfoJson) as Map<String, dynamic>;
            subscriptionId = userInfo['open_id']?.toString() ?? 
                            userInfo['snowflake_id']?.toString() ?? 
                            userInfo['username']?.toString();
          } catch (e) {
            developer.log('Failed to parse user info for subscription_id: $e', name: 'WebSocketServiceRust');
          }
        }
      }

      if (subscriptionId == null || subscriptionId.isEmpty) {
        developer.log('No subscription_id found, cannot connect WebSocket', name: 'WebSocketServiceRust');
        _status = LocalWebSocketStatus.error;
        _notifyStatusChange();
        return;
      }

      // 构建WebSocket URL
      final wsBaseUrl = AppConfig.wsBaseUrl;
      final wsUrl = '$wsBaseUrl/$subscriptionId';
      developer.log('WebSocket URL: $wsUrl', name: 'WebSocketServiceRust');
      developer.log('Using subscription_id: $subscriptionId', name: 'WebSocketServiceRust');

      // 创建 WebSocketManager（从 Rust 生成）
      // 注意：需要先运行代码生成才能使用
      // 如果编译错误，请运行：cd rust && flutter_rust_bridge_codegen generate
      _manager = WebSocketManager();

      // 创建状态流和消息流
      // 在 flutter_rust_bridge 中，StreamSink 需要从 Dart 端创建
      final statusSink = StreamSink<WebSocketStatus>();
      final messageSink = StreamSink<WebSocketMessage>();

      // 监听状态流
      _statusSubscription = statusSink.stream.listen((rustStatus) {
        _handleRustStatus(rustStatus);
      });

      // 监听消息流
      _messageSubscription = messageSink.stream.listen((rustMessage) {
        _handleRustMessage(rustMessage);
      });

      // 连接（传递流）
      try {
        _manager!.connect(
          subscriptionId: subscriptionId,
          wsUrl: wsUrl,
          token: token,
          statusSink: statusSink,
          messageSink: messageSink,
        );
        
        // 注意：连接是异步的，实际状态会通过statusSink流通知
        // 这里不立即设置为connected，等待Rust端通知
        developer.log('WebSocket connection initiated (Rust)', name: 'WebSocketServiceRust');
      } on UnimplementedError catch (e) {
        // Rust WebSocket 实现尚未可用，提供详细的错误信息
        developer.log('Rust WebSocket 实现尚未可用: $e', name: 'WebSocketServiceRust');
        developer.log(
          '请按照以下步骤修复：\n'
          '1. 进入 rust 目录: cd violet_mobile/rust\n'
          '2. 运行代码生成: flutter_rust_bridge_codegen generate\n'
          '3. 如果遇到配置问题，请查看 rust/GENERATE_BINDINGS.md\n'
          '4. 重新编译项目',
          name: 'WebSocketServiceRust'
        );
        _status = LocalWebSocketStatus.error;
        _notifyStatusChange();
        // 不自动重连，因为需要先修复代码生成问题
        rethrow;
      } catch (e) {
        developer.log('WebSocket connection failed: $e', name: 'WebSocketServiceRust');
        _status = LocalWebSocketStatus.error;
        _notifyStatusChange();
        _scheduleReconnect();
        rethrow;
      }
    } catch (e) {
      developer.log('❌ WebSocket connection failed: $e', name: 'WebSocketServiceRust');
      _status = LocalWebSocketStatus.error;
      _notifyStatusChange();
      _scheduleReconnect();
    }
  }

  void _handleRustStatus(WebSocketStatus rustStatus) {
    developer.log('WebSocket status changed: $rustStatus', name: 'WebSocketServiceRust');
    
    // 将 Rust 的 WebSocketStatus 枚举映射到本地状态
    // Rust 枚举: Disconnected, Connecting, Connected, Error(String)
    // 注意：flutter_rust_bridge 生成的枚举可能是不同的格式
    // 如果编译错误，请检查生成的代码中的实际类型名称
    
    // 尝试使用模式匹配（如果生成的代码支持）
    try {
      // 使用字符串匹配来处理枚举（兼容不同版本的 flutter_rust_bridge）
      final statusStr = rustStatus.toString();
      if (statusStr.contains('Connecting') || statusStr == 'WebSocketStatus.Connecting') {
        _status = LocalWebSocketStatus.connecting;
      } else if (statusStr.contains('Connected') || statusStr == 'WebSocketStatus.Connected') {
        _status = LocalWebSocketStatus.connected;
        _reconnectAttempts = 0;
        developer.log('WebSocket connected successfully (Rust)', name: 'WebSocketServiceRust');
      } else if (statusStr.contains('Disconnected') || statusStr == 'WebSocketStatus.Disconnected') {
        _status = LocalWebSocketStatus.disconnected;
        developer.log('WebSocket disconnected (Rust)', name: 'WebSocketServiceRust');
        _scheduleReconnect();
      } else if (statusStr.contains('Error')) {
        _status = LocalWebSocketStatus.error;
        developer.log('WebSocket error: $statusStr', name: 'WebSocketServiceRust');
        _scheduleReconnect();
      } else {
        // 未知状态，记录日志
        developer.log('Unknown WebSocket status: $statusStr', name: 'WebSocketServiceRust');
      }
    } catch (e) {
      developer.log('Error handling Rust status: $e', name: 'WebSocketServiceRust');
    }
    _notifyStatusChange();
  }

  void _handleRustMessage(WebSocketMessage rustMessage) {
    try {
      developer.log('_handleRustMessage called: type=${rustMessage.messageType}, data length=${rustMessage.data.length}', name: 'WebSocketServiceRust');
      
      if (rustMessage.messageType == 'text') {
        try {
          final messageMap = jsonDecode(rustMessage.data) as Map<String, dynamic>;
          developer.log('Received WebSocket message: ${messageMap['message_id'] ?? 'unknown'}', name: 'WebSocketServiceRust');
          developer.log('Message content: ${messageMap.toString().substring(0, messageMap.toString().length > 200 ? 200 : messageMap.toString().length)}', name: 'WebSocketServiceRust');
          
          // 检查是否是 ping/pong 消息，如果是则忽略
          if (messageMap['type'] == 'ping' || messageMap['type'] == 'pong') {
            developer.log('Ignoring ping/pong message', name: 'WebSocketServiceRust');
            return;
          }
          
          // 添加到消息流
          if (_messageController != null && !_messageController!.isClosed) {
            _messageController!.add(messageMap);
            developer.log('Message added to _messageController, has listeners: ${_messageController!.hasListener}', name: 'WebSocketServiceRust');
          } else {
            developer.log('_messageController is null or closed', name: 'WebSocketServiceRust');
          }
        } catch (jsonError) {
          developer.log('Failed to parse JSON message: $jsonError', name: 'WebSocketServiceRust');
          developer.log('Raw message data: ${rustMessage.data}', name: 'WebSocketServiceRust');
          // 即使解析失败，也尝试添加原始数据
          if (_messageController != null && !_messageController!.isClosed) {
            _messageController!.add(rustMessage.data);
          }
        }
      } else {
        developer.log('Received WebSocket message (${rustMessage.messageType}): ${rustMessage.data.substring(0, rustMessage.data.length > 100 ? 100 : rustMessage.data.length)}', name: 'WebSocketServiceRust');
        if (_messageController != null && !_messageController!.isClosed) {
          _messageController!.add(rustMessage.data);
        }
      }
    } catch (e, stackTrace) {
      developer.log('Error handling WebSocket message: $e', name: 'WebSocketServiceRust');
      developer.log('Stack trace: $stackTrace', name: 'WebSocketServiceRust');
      if (_messageController != null && !_messageController!.isClosed) {
        _messageController!.add(rustMessage.data);
      }
    }
  }

  void disconnect() {
    developer.log('Disconnecting WebSocket (Rust)...', name: 'WebSocketServiceRust');
    _stopPingTimer();
    _reconnectTimer?.cancel();
    _statusSubscription?.cancel();
    _messageSubscription?.cancel();
    _manager?.disconnect();
    _manager = null;
    _status = LocalWebSocketStatus.disconnected;
    _notifyStatusChange();
    developer.log('WebSocket disconnected (Rust)', name: 'WebSocketServiceRust');
  }

  void send(dynamic message) {
    if (_status == LocalWebSocketStatus.connected && _manager != null) {
      try {
        String messageStr;
        if (message is String) {
          messageStr = message;
        } else if (message is Map) {
          messageStr = jsonEncode(message);
        } else {
          messageStr = message.toString();
        }
        _manager!.send(messageStr);
        developer.log('Sent WebSocket message: ${messageStr.length > 100 ? messageStr.substring(0, 100) + "..." : messageStr}', name: 'WebSocketServiceRust');
      } catch (e) {
        developer.log('Error sending WebSocket message: $e', name: 'WebSocketServiceRust');
      }
    } else {
      developer.log('Cannot send message: WebSocket not connected (status: $_status)', name: 'WebSocketServiceRust');
    }
  }

  void _scheduleReconnect() {
    if (_reconnectAttempts >= maxReconnectAttempts) {
      return;
    }

    _reconnectTimer?.cancel();
    _reconnectAttempts++;
    final delay = Duration(seconds: _reconnectAttempts * 2);

    _reconnectTimer = Timer(delay, () {
      if (_status != LocalWebSocketStatus.connected) {
        connect();
      }
    });
  }

  void _notifyStatusChange() {
    _statusController?.add(_status);
  }

  void _stopPingTimer() {
    // Ping 由 Rust 端自动处理
  }

  void dispose() {
    disconnect();
    _messageController?.close();
    _statusController?.close();
    _reconnectTimer?.cancel();
  }
}

